#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

int main()
{
	int socketfd = socket(AF_INET, SOCK_STREAM, 0);
	if(socketfd == -1){
			printf("socket error\n");
			return -1;
	}

	struct sockaddr_in serveraddr, clientaddr;
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_port = htons(2250);//htons (host to network short)将主机字节序转化为网络字节序，网络字节序为大端字节序
	serveraddr.sin_addr.s_addr = inet_addr("192.168.220.128");//inet_addr 将地址字符串转化为整型数据，具体可以查看(struct sockaddr_in \ struct sockaddr \ in_addr )的相关定义
	if(bind(socketfd, (struct sockaddr*)&serveraddr, sizeof(serveraddr)) < 0){ //需要注意地址的类型
		printf("bind error\n");
		return -1;
	}

	if(listen(socketfd, 10) < 0){
		printf("listen error\n");
		return -1;
	}

	socklen_t addrlen = sizeof(clientaddr);	
	int acceptfd;	
	char mpidinput[64];
/*创建子进程，主进程负责关闭服务器（在终端中输入quit，sever退出），子进程负责接受client的数据*/
	int mpid = fork();
	if(mpid < 0){
	printf("fork error in mpid\n");
	return -1;
	}
	/*子进程负责接收client发送的数据*/
	if(mpid == 0){
		while(1){
			acceptfd = accept(socketfd, (struct sockaddr*)&clientaddr, &addrlen);
			if(acceptfd < 0){
			printf("accept error\n");
			return -1;
			}

			printf("connected\n");
			printf("client addr : %s\n",inet_ntoa(clientaddr.sin_addr));//inet_ntoa 将整型地址转化为字符串类型
			int pid = fork();//
			if(pid < 0){
				printf("fork error\n");
				return -1;
			}

			else if(pid == 0){
				char buf[64];
				ssize_t recvdata;
				while(1){
					if((recvdata = recv(acceptfd, (void*)buf, sizeof(buf), 0)) < 0){
					printf("recv error\n");
					return -1;
					}
					else if(recvdata == 0){//当client断推出时，recvdata = 0;
						goto closerecv;
					}
					printf("ID=%d:%s",getpid(), buf);
					if(strncmp(buf, "quit", 4) == 0){
closerecv:				
						close(acceptfd);
						exit(0);
					}
				}
			}

			printf("child pid = %d\n",pid);		
		}//while(1)
		//while(wait(NULL) != -1 );//等待所有进程结束
		return 0;
	}//if(mpid == 0)
	/*主进程负责服务器的关闭*/
	while(1){
		if(gets(mpidinput) == NULL){
			printf("gets errro in mpidinput\n");
			return -1;
		}
		if(strncmp(mpidinput, "quit", 4) == 0){
			printf("sever offline\n");
			break;
		}
	}

	kill(mpid, SIGKILL);
	waitpid(mpid, NULL,  0);	
	close(socketfd);
	return 0;
}//int main()
